package ph.com.gs3.formalistics.communicators;

import org.json.JSONException;
import org.json.JSONObject;

import ph.com.gs3.formalistics.communicators.CommunicatorModule.CommunicatorException;
import ph.com.gs3.formalistics.mock.FakeCommunicator;
import ph.com.gs3.formalistics.model.valueobjects.application.APIResponse;
import ph.com.gs3.formalistics.model.valueobjects.application.APIResponse.APIInvalidResponseException;
import android.test.AndroidTestCase;
import android.util.Log;

public class AuthenticationCommunicatorModuleTest extends AndroidTestCase {

	public static final String TAG = AuthenticationCommunicatorModuleTest.class.getSimpleName();

	protected void setUp() throws Exception {
		super.setUp();
	}

	public void testFailingLogin() {

		FakeCommunicator fakeCommunicator = new FakeCommunicator();

		fakeCommunicator
		        .setFakeResponse("<p>This should result in invalid response, since this is not a JSON object</p>");

		AuthenticationCommunicatorModule module = new AuthenticationCommunicatorModule(
		        fakeCommunicator, "");

		// try {
		// APIResponse response = module.login("ervinne.sodusta@gs3.com.ph", "password");
		//
		// Log.v(TAG, response.toString());
		//
		// // fail(response.toString());
		//
		// if (response.operationSuccessful()) {
		// fail(response.getErrorMessage());
		// }
		//
		// } catch (CommunicatorException e) {
		// fail("Unexepcted CommunicatorException: " + e.getMessage());
		// } catch (APIResponseException e) {
		// fail("Unexepcted APIResponseException: " + e.getMessage());
		// }

		try {
			module.login("ervinne.sodusta@gs3.com.ph", "password");
			fail("CommunicatorException is expected since server gave invalid response");
		} catch (CommunicatorException e) {
			Log.v(TAG, "Correct exception is thrown: " + e.getMessage());
		} catch (APIInvalidResponseException e) {
			fail("CommunicatorException is expected since server gave invalid response, but APIResponseException is thrown instead.");
		}

		try {
			module.login(null, "password");
			fail("null email should not be allowed");
		} catch (CommunicatorException e) {
			Log.v(TAG, "Correct exception is thrown: " + e.getMessage());
		} catch (APIInvalidResponseException e) {
			fail("CommunicatorException is expected since server gave invalid response, but APIResponseException is thrown instead.");
		}

		try {
			module.login("ervinne.sodusta@gs3.com.ph", null);
			fail("null password should not be allowed");
		} catch (CommunicatorException e) {
			Log.v(TAG, "Correct exception is thrown: " + e.getMessage());
		} catch (APIInvalidResponseException e) {
			fail("CommunicatorException is expected since server gave invalid response, but APIResponseException is thrown instead.");
		}

	}

	public void testValidLoginWithFakeCommunicator() {

		FakeCommunicator fakeCommunicator = new FakeCommunicator();
		JSONObject fakeServerResponse = new JSONObject();

		try {
			fakeServerResponse.put("status", "SUCCESS");
			fakeServerResponse.put("error", "null");
			fakeServerResponse.put("error_message", "null");
			fakeServerResponse.put("results", new JSONObject());

			fakeCommunicator.setFakeResponse(fakeServerResponse.toString());
			AuthenticationCommunicatorModule module = new AuthenticationCommunicatorModule(
			        fakeCommunicator, "");

			APIResponse response = module.login("ervinne.sodusta@gs3.com.ph", "password");

			Log.v(TAG, fakeServerResponse.toString());
			Log.v(TAG, response.toString());

			assertTrue(response.operationSuccessful());
			assertEquals(fakeServerResponse.get("error"), response.getError());
			assertEquals(fakeServerResponse.get("error_message"), response.getErrorMessage());
			assertEquals(fakeServerResponse.getJSONObject("results").toString(), response
			        .getResults().toString());

		} catch (JSONException e) {
			fail("Unexpected JSONException while writing test");
		} catch (CommunicatorException e) {
			fail("Unexpected CommunicatorException " + e.getMessage());
		} catch (APIInvalidResponseException e) {
			fail("Unexpected APIResponseException " + e.getMessage());
		}

	}

	/**
	 * Comment this out if you only need to test with mocks and not with actual data.
	 */
	public void testValidLoginToServer() {

		Communicator communicator = new Communicator();

		try {
			AuthenticationCommunicatorModule module = new AuthenticationCommunicatorModule(
			        communicator, "192.168.0.101");

			APIResponse response = module.login("ervinne.sodusta@gs3.com.ph", "password");

			assertTrue(response.operationSuccessful());
			assertNull(response.getError());
			assertNull(response.getErrorMessage());
			assertNotNull(response.getResults());

		} catch (CommunicatorException e) {
			fail("Unexpected CommunicatorException " + e.getMessage());
		} catch (APIInvalidResponseException e) {
			fail("Unexpected APIResponseException " + e.getMessage());
		}

	}

}
